package com.administration.controller;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.faces.context.FacesContext;
import javax.inject.Singleton;
import javax.persistence.EntityManager;
import javax.servlet.http.HttpSession;

import com.administration.entity.Access;
import com.administration.entity.Category;
import com.administration.entity.GroupPrivilege;
import com.administration.entity.Groups;
import com.administration.entity.Privilege;
import com.administration.entity.User;
import com.administration.entity.resultsetmapping.PrivilegeMapping;
import com.common.Constant;
import com.common.Utility;
import com.core.transaction.EntityManagerClass;
import com.entity.RegisteredUser;

@Singleton
public class AdministrationController implements Serializable {// extends
																// BaseDAOImpl {
	private static final long serialVersionUID = 1L;
	RegisteredUser registeredUser;
	HttpSession session;
	EntityManager em = null;

	// static EntityManagerFactory emf;

	public AdministrationController() {
		session = (HttpSession) FacesContext.getCurrentInstance()
				.getExternalContext().getSession(true);

		registeredUser = (RegisteredUser) session
				.getAttribute("registeredUser");
		if (registeredUser == null) {
			registeredUser = new RegisteredUser();
		}
		// em = getEntityManager();
		// emf = Persistence
		// .createEntityManagerFactory("aqarat");// "$objectdb/db/points.odb"
		// em = emf.createEntityManager();
		em = EntityManagerClass.getEntityManagerFactory().createEntityManager();
	}

	// ----------------------------------------------------------//
	// -------------------------Category-------------------------//
	// ----------------------------------------------------------//
	public Category getCategoryById(Long categoryId) throws Exception {
		String sql = "select c from Category c where c.categoryId=:categoryId";
		return (Category) em.createQuery(sql)
				.setParameter("categoryId", categoryId).getSingleResult();
	}

	public List<Category> getAllCategories() throws Exception {
		String sql = "select c from Category c ";
		return em.createQuery(sql).getResultList();
	}

	// ----------------------------------------------------------//
	// -------------------------Group----------------------------//
	// ----------------------------------------------------------//

	public Long addGroup(Groups group) throws Exception {
		try {
			em.getTransaction().begin();
			em.persist(group);
			em.getTransaction().commit();
			return group.getRecid();
		} catch (Exception ex) {
			em.getTransaction().rollback();
			ex.printStackTrace();
			throw ex;
		}
		// finally {
		// if (em != null) {
		// em.close();
		// }
		// }

	}

	public void deleteGroup(Groups group) throws Exception {
		try {
			em.getTransaction().begin();
			em.remove(group);
			em.getTransaction().commit();
		} catch (Exception ex) {
			em.getTransaction().rollback();
			ex.printStackTrace();
			throw ex;
		}
		// finally {
		// if (em != null) {
		// em.close();
		// }
		// }
	}

	public Groups getGroupById(Long groupId) throws Exception {
		String sql = "select g from Groups g where g.recid=:recid";
		return (Groups) em.createQuery(sql).setParameter("recid", groupId)
				.getSingleResult();

	}

	public void updateGroup(Groups group) throws Exception {
		try {
			em.getTransaction().begin();
			em.merge(group);
			em.getTransaction().commit();
		} catch (Exception ex) {
			em.getTransaction().rollback();
			ex.printStackTrace();
			throw ex;
		}
		// finally {
		// if (em != null) {
		// em.close();
		// }
		// }
	}

	public List<Groups> getAllGroups() throws Exception {
		// String sql = "select g from Group g ";
		return em.createQuery("select g from Groups g").getResultList();
	}

	// ----------------------------------------------------------//
	// -------------------------Access----------------------------//
	// ----------------------------------------------------------//

	public Long addAccess(Access access) throws Exception {
		try {
			em.getTransaction().begin();
			em.persist(access);
			em.getTransaction().commit();
			return access.getRecid();
		} catch (Exception ex) {
			em.getTransaction().rollback();
			ex.printStackTrace();
			throw ex;
		}
		// finally {
		// if (em != null) {
		// em.close();
		// }
		// }
	}

	public void updateAccess(Access access) throws Exception {
		try {
			em.getTransaction().begin();
			em.merge(access);
			em.getTransaction().commit();
		} catch (Exception ex) {
			em.getTransaction().rollback();
			ex.printStackTrace();
			throw ex;
		}
		// finally {
		// if (em != null) {
		// em.close();
		// }
		// }
	}

	public void delateAccess(Access access) throws Exception {
		try {
			em.getTransaction().begin();
			em.remove(access);
			em.getTransaction().commit();
		} catch (Exception ex) {
			em.getTransaction().rollback();
			ex.printStackTrace();
			throw ex;
		}
		// finally {
		// if (em != null) {
		// em.close();
		// }
		// }
	}

	public List<Access> getAllAccess() throws Exception {
		String sql = "select a from Access a";
		return em.createQuery(sql).getResultList();
	}

	// ----------------------------------------------------------------//
	// ----------------------------------------------------------------//
	// ----------------------------------------------------------------//

	public Long addPrivilege(Privilege privilage) throws Exception {
		try {
			em.getTransaction().begin();
			em.persist(privilage);
			em.getTransaction().commit();
			return privilage.getRecid();
		} catch (Exception ex) {
			em.getTransaction().rollback();
			ex.printStackTrace();
			throw ex;
		}
		// finally {
		// if (em != null) {
		// em.close();
		// }
		// }
	}

	public void updatePrivilege(Privilege privilage) throws Exception {
		try {
			em.getTransaction().begin();
			em.merge(privilage);
			em.getTransaction().commit();
		} catch (Exception ex) {
			em.getTransaction().rollback();
			ex.printStackTrace();
			throw ex;
		}
		// finally {
		// if (em != null) {
		// em.close();
		// }
		// }
	}

	public void delatePrivilege(Privilege privilege) throws Exception {
		try {
			em.getTransaction().begin();
			em.remove(privilege);
			em.getTransaction().commit();
		} catch (Exception ex) {
			em.getTransaction().rollback();
			ex.printStackTrace();
			throw ex;
		}
		// finally {
		// if (em != null) {
		// em.close();
		// }
		// }
	}

	public List<Privilege> getAllPrivileges() throws Exception {
		String sql = "select p from Privilege p";
		return em.createQuery(sql).getResultList();
	}

	// ----------------------------------------------------------//
	// --------------------Privilege-----------------------------//
	// ----------------------------------------------------------//
	public List<PrivilegeMapping> getAllPrivilegeMappingList() throws Exception {
		String sql = "select p from Privilege p";
		List<Privilege> privilegeList = em.createQuery(sql).getResultList();
		List<PrivilegeMapping> privilegeMappingList = new ArrayList<PrivilegeMapping>();
		for (Privilege privilege : privilegeList) {
			PrivilegeMapping privilegeMapping = new PrivilegeMapping();
			privilegeMapping.setPrivilegeId(privilege.getRecid());
			privilegeMapping.setPrivilegeName(privilege.getName());
			privilegeMappingList.add(privilegeMapping);
		}
		return privilegeMappingList;
	}

	public void saveAllPrivilegeMapping(
			List<PrivilegeMapping> PrivilegeMappingList, Long groupRecId)
			throws Exception {
		em.getTransaction().begin();
		for (PrivilegeMapping privilegeMapping : PrivilegeMappingList) {
			if (privilegeMapping.getAccessId() == Constant.NO_ACCESS) {

				em.remove(new GroupPrivilege(groupRecId, privilegeMapping
						.getPrivilegeId()));
				// this.delateGroupPrivilages(new GroupPrivilege(groupRecId,
				// privilegeMapping.getPrivilegeId()));
			}
			if (privilegeMapping.getAccessId() == Constant.ACCESS) {

				// Boolean b = isGroupPrivilagesFound(new GroupPrivilege(
				// groupRecId, privilegeMapping.getPrivilegeId(),
				// privilegeMapping.getAccessId()));
				Boolean b = (privilegeMapping.getRecId() == null ? false : true);
				if (b == false) {
					em.persist(new GroupPrivilege(groupRecId, privilegeMapping
							.getPrivilegeId(), privilegeMapping.getAccessId()));
					// this.addGroupPrivileges(new GroupPrivilege(groupRecId,
					// privilegeMapping.getPrivilegeId(), privilegeMapping
					// .getAccessId()));
				}
			}
		}
		em.getTransaction().commit();
		setRegistredUserPrivileges(registeredUser);

	}

	// ----------------------------------------------------------//
	// -------------------GroupPrivilege---------------------//
	// ----------------------------------------------------------//

	public Long addGroupPrivileges(GroupPrivilege groupPrivilages)
			throws Exception {
		try {
			em.getTransaction().begin();
			em.persist(groupPrivilages);
			em.getTransaction().commit();
			return groupPrivilages.getRecid();
		} catch (Exception ex) {
			em.getTransaction().rollback();
			ex.printStackTrace();
			throw ex;
		}
		// finally {
		// if (em != null) {
		// em.close();
		// }
		// }
	}

	public void updateGroupPrivileges(GroupPrivilege groupPrivileges)
			throws Exception {
		try {
			em.getTransaction().begin();
			em.merge(groupPrivileges);
			em.getTransaction().commit();
		} catch (Exception ex) {
			em.getTransaction().rollback();
			ex.printStackTrace();
			throw ex;
		}
		// finally {
		// if (em != null) {
		// em.close();
		// }
		// }
	}

	public void delateGroupPrivilages(GroupPrivilege groupPrivileges)
			throws Exception {
		try {
			em.getTransaction().begin();
			em.remove(groupPrivileges);
			em.getTransaction().commit();
		} catch (Exception ex) {
			em.getTransaction().rollback();
			ex.printStackTrace();
			throw ex;
		}
		// finally {
		// if (em != null) {
		// em.close();
		// }
		// }
	}

	// public Boolean isGroupPrivilagesFound(GroupPrivilege groupPrivilege)
	// throws Exception {
	// return administrationDao.isGroupPrivilagesFound(groupPrivilege);
	// }

	public List<GroupPrivilege> getAllGroupPrivileges(Long groupRecId)
			throws Exception {
		String sql = "select gp from GroupPrivilege gp where gp.groupId=:groupId";
		return em.createQuery(sql).setParameter("groupId", groupRecId)
				.getResultList();

	}

	public void saveAllGroupPrivilege(List<GroupPrivilege> groupPrivilegeList)
			throws Exception {
		try {
			em.getTransaction().begin();
			for (GroupPrivilege groupPrivilege : groupPrivilegeList) {
				if (groupPrivilege.getGroupId() == null) {
					em.persist(groupPrivilege);

				} else {
					em.merge(groupPrivilege);
				}
			}
			em.getTransaction().commit();
		} catch (Exception ex) {
			em.getTransaction().rollback();
			ex.printStackTrace();
			throw ex;
		}
		// finally {
		// if (em != null) {
		// em.close();
		// }
		// }
	}

	// ----------------------------------------------------------//
	// --------------------------User----------------------------//
	// ----------------------------------------------------------//

	public User getUser(String userName, String password) throws Exception {
		String sql = "select u from User u where u.userName=:userName and u.password=:password";
		return (User) em.createQuery(sql).setParameter("userName", userName)
				.setParameter("password", password).getSingleResult();
	}

	public Long addUser(User user) throws Exception {
		String pass = Utility.PasswordEncrypt(user.getPassword());
		user.setPassword(pass);
		try {
			em.getTransaction().begin();
			em.persist(user);
			em.getTransaction().commit();
			return user.getUserId();
		} catch (Exception ex) {
			em.getTransaction().rollback();
			ex.printStackTrace();
			throw ex;
		}
		// finally {
		// if (em != null) {
		// em.close();
		// }
		// }
	}

	public void updateUser(User user) throws Exception {
		String pass = Utility.PasswordEncrypt(user.getPassword());
		user.setPassword(pass);
		try {
			em.getTransaction().begin();
			em.merge(user);
			em.getTransaction().commit();
		} catch (Exception ex) {
			em.getTransaction().rollback();
			ex.printStackTrace();
			throw ex;
		}
		// finally {
		// if (em != null) {
		// em.close();
		// }
		// }
	}

	public void deleteUser(User user) throws Exception {
		try {
			em.getTransaction().begin();
			em.remove(user);
			em.getTransaction().commit();
		} catch (Exception ex) {
			em.getTransaction().rollback();
			ex.printStackTrace();
			throw ex;
		}
		// finally {
		// if (em != null) {
		// em.close();
		// }
		// }
	}

	public User getUserById(Long userId) throws Exception {
		String sql = "select u from User u where u.recid=:userId";
		User user = (User) em.createQuery(sql).setParameter("userId", userId)
				.getSingleResult();
		String pass = Utility.PasswordEncrypt(user.getPassword());
		user.setPassword(pass);
		return user;
	}

	public User getUser(String userName) throws Exception {
		String sql = "select u from User u where u.userName=:userName";
		return (User) em.createQuery(sql).setParameter("userName", userName)
				.getSingleResult();
	}

	public User getUserByEmail(String email) throws Exception {
		String sql = "select u from User u where u.email=:email";
		return (User) em.createQuery(sql).setParameter("email", email)
				.getSingleResult();
	}

	public List<User> getListUserByGroupId(Long groupId) throws Exception {
		String sql = "select u from User u where u.groupId=:groupId";
		return em.createQuery(sql).setParameter("groupId", groupId)
				.getResultList();
	}

	public List<User> getAllUsers() throws Exception {
		String sql = "select u from User u ";
		return em.createQuery(sql).getResultList();
	}

	public Groups getgroupById(Long groupId) throws Exception {
		String sql = "select g from Groups g where g.groupId=:groupId";
		return (Groups) em.createQuery(sql).setParameter("groupId", groupId)
				.getSingleResult();
	}

	public List<Groups> getListGroups() throws Exception {
		String sql = "select g from Groups g ";
		return em.createQuery(sql).getResultList();
	}

	// ----------------------------------------------------------//
	// ----------------------------------------------------------//
	// ----------------------------------------------------------//

	public Long saveGroupWithPrivileges(Groups group,
			List<PrivilegeMapping> PrivilegeMappingList) throws Exception {
		try {
			Long groupId;
			em.getTransaction().begin();

			if (group.getRecid() == null) {
				em.persist(group);

				groupId = group.getRecid();
			} else {
				em.merge(group);
				groupId = group.getRecid();
			}

			// --------------------------//
			for (PrivilegeMapping privilegeMapping : PrivilegeMappingList) {
				if (privilegeMapping.getAccessId() == Constant.NO_ACCESS) {
					if (privilegeMapping.getRecId() != null) {
						GroupPrivilege gp = new GroupPrivilege();
						gp.setRecid(privilegeMapping.getRecId());
						gp.setGroupId(groupId);
						gp.setPrivilageId(privilegeMapping.getPrivilegeId());
						// gp.setAccessId(Constant.ACCESS);
						// em.remove(gp);
						gp.setAccessId(Constant.NO_ACCESS);
						em.merge(gp);
					}
				}
				if (privilegeMapping.getAccessId() == Constant.ACCESS) {

					if (privilegeMapping.getRecId() == null) {
						em.persist(new GroupPrivilege(groupId, privilegeMapping
								.getPrivilegeId(), privilegeMapping
								.getAccessId()));
					}
				}
			}
			// --------------------------//

			em.getTransaction().commit();
			// saveAllPrivilegeMapping(PrivilegeMappingList, groupId);
			return groupId;
		} catch (Exception ex) {
			em.getTransaction().rollback();
			ex.printStackTrace();
			throw ex;
		}
		// finally {
		// if (em != null) {
		// em.clear();
		// }
		// }

	}

	public void deleteGroupWithPrivileges(Groups group) throws Exception {
		try {
			em.getTransaction().begin();

			em.createQuery(
					"delete from GroupPrivilege gp where gp.groupId=:groupId")
					.setParameter("groupId", group.getRecid()).executeUpdate();
			em.remove(group);

			em.getTransaction().commit();
		} catch (Exception ex) {
			em.getTransaction().rollback();
			ex.printStackTrace();
			throw ex;
		}
		// finally {
		// if (em != null) {
		// em.close();
		// }
		// }

	}

	public RegisteredUser loginUser(String userName, String password)
			throws Exception {

		User user = this.getUser(userName, password);
		if (user == null) {
			return null;
		}
		Groups group = this.getGroupById(user.getGroupId());
		if (group == null) {
			return null;
		}
		if (group.getStatus() != 1) {
			return null;
		}

		registeredUser.setUserId(user.getUserId());
		registeredUser.setGroupId(group.getRecid());
		setRegistredUserPrivileges(registeredUser);
		return registeredUser;

	}

	public void setRegistredUserPrivileges(RegisteredUser registeredUser)
			throws Exception {
		List<PrivilegeMapping> pml = this
				.getPrivilegeMappingList(registeredUser.getGroupId());

		registeredUser.setPrivilegeMappingList(pml);
		List<Long> categoryRecIdList = new ArrayList<Long>();
		boolean isCatIdFound = false;
		for (PrivilegeMapping pm : pml) {
			if (categoryRecIdList.size() == 0) {
				categoryRecIdList.add(pm.getCategoryId());
			} else {
				for (Long l : categoryRecIdList) {
					if (l.equals(pm.getCategoryId())) {
						isCatIdFound = true;
						break;
					} else {
						isCatIdFound = false;

					}
				}
				if (isCatIdFound == false) {
					categoryRecIdList.add(pm.getCategoryId());
				}
			}

		}
		registeredUser.setCategoryList(categoryRecIdList);
	}

	public List<PrivilegeMapping> getPrivilegeMappingList(Long groupId)
			throws Exception {
		String sql = "select distinct gp.recid as recid,gp.group_id as groupId ,gp.privilege_id as privilegeId,gp.access_id as accessId,p.category_id as categoryId,p.name as privilegeName "
				+ " from group_privileges gp, privilege p  where gp.privilege_id=p.recid and gp.group_id="
				+ groupId;
		return (List<PrivilegeMapping>) (em.createNativeQuery(sql,
				PrivilegeMapping.class).getResultList());

	}
}
